home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / libs / 3dvect39 / xscale.inc < prev   
Encoding:
Text File  |  1994-10-30  |  41.8 KB  |  872 lines

  1. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2. ;
  3. ; Filename     : xscale.inc
  4. ; Included from: 3D1.ASM, 3D2.ASM, 3D3.ASM
  5. ; Description  : bitmap Scaling routines - non-cartisian plotting
  6. ;
  7. ; _xscale1.ASM by John A. Slagel, jas37876@uxa.cso.uiuc.edu
  8. ; This is some code to do bitmap scaling in VGA Mode X.  It can scale a
  9. ; bitmap of any size down to 2 pixels wide, or up to thousands of pixels
  10. ; wide.  It performs complete clipping, with only a small constant amount
  11. ; of time to clip, no matter how huge the image is.  It draws column by
  12. ; column to reduce the number of plane switches, which are slow. The inner
  13. ; column loop has been optimized for no memory accesses, except to read or
  14. ; write a pixel.  This uses MASM 5.1 features, and can be compiled in any
  15. ; memory model by changing the .MODEL line, but make sure that you always
  16. ; pass a far pointer to the bitmap data, regardless of memory model.
  17. ; C-callable as:
  18. ;   void _xscale1( int X, int Y, int DW, int DY,
  19. ;                     int SW, int SH, void far * bitmap );
  20. ; X,Y   are the upper left-hand coordinates of where to draw the bitmap.
  21. ; DW,DH are the width and height of the SCALEed _bitmap
  22. ; SW,SH are the width and height of the source _bitmap.
  23. ; _bitmap is a pointer to the _bitmap bits.
  24. ;
  25. ; Routine has been modified for 32 bit protected mode by John McCarthy.
  26. ; John McCarthy thanks John A. Slagel for providing this code, and hopes
  27. ; John A. Slagel is not offended by the changes.
  28. ;
  29. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  30.  
  31.          public _draw_scale
  32.          public _tdraw_scale
  33.          public _tdraw_scale4
  34.          public _xscale1
  35.          public _xscale2
  36.          public _xscale4
  37.          public _repeat_bitmap
  38.  
  39. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  40. ;
  41. ; _draw_scale - draw scaled _bitmap in modex
  42. ; In:
  43. ;    ESI - offset of _bitmap to draw, first two words are x,y size
  44. ;     AX - x width to scale to
  45. ;     BX - y width to scale to
  46. ;     CX - x location, non-cartisian
  47. ;     DX - y location, non-cartisian
  48. ; _current_page - current offset of video memory for page of xmode, see xmode.asm
  49. ;
  50. ; Out:
  51. ;    null
  52. ;
  53. ; Notes:
  54. ;  destructive bitmap - non-cartisian
  55. ;
  56. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  57.  
  58. _draw_scale:
  59.          mov _bitmap,esi
  60.          mov _scale_destwidth,ax
  61.          mov _scale_destheight,bx
  62.          mov _scale_destx,cx
  63.          mov _scale_desty,dx
  64.  
  65. _xscale1:
  66.          cmp _scale_destwidth, 2            ; if destination width is less than 2
  67.          jl done                            ;     then don't draw it.
  68.  
  69.          cmp _scale_destheight, 2           ; if destination height is less than 2
  70.          jl done                            ;     then don't draw it.
  71.  
  72.          mov ax, _scale_desty               ; if it is completely below the
  73.          cmp ax, _clipbt                    ; lower clip bondry,
  74.          jg done                            ;     then don't draw it.
  75.  
  76.          add ax, _scale_destheight          ; if it is above clip boundries
  77.          dec ax                             ;     then don't draw it.
  78.          cmp ax, _cliptp
  79.          jl done
  80.  
  81.          mov ax, _scale_destx               ; if it is to the right of the
  82.          mov cx, _cliprt                    ; right clip boundry
  83.          cmp ax, _cliprt                    ;     then don't draw it.
  84.          jg done
  85.  
  86.          add ax, _scale_destwidth           ; if it is completely to the left
  87.          dec ax                             ; of the left clip boundry,
  88.          cmp ax, _cliplt                    ;     then don't draw it.
  89.          jl done
  90.  
  91.          mov esi, _bitmap             ; make esi point to _bitmap data
  92.          lodsw                              ; get source x width
  93.          mov sourcewidth,ax
  94.          lodsw                              ; get source y height
  95.          mov sourceheight,ax
  96.  
  97.          mov ax, _scale_destwidth           ; clippedwidth is initially set to
  98.          mov clippedwidth, ax               ; the requested dest width.
  99.  
  100.          add ax,ax                          ; initialize the x decision var
  101.          neg ax                             ; to be -2*_scale_destwidth
  102.          mov decisionx, ax                  ;
  103.  
  104.          mov ax, _scale_destheight          ; clippedheight is initially set to
  105.          mov clippedheight, ax              ; the requested dest size.
  106.  
  107.          add ax,ax                          ; initialize the y decision var
  108.          neg ax                             ; to be -2*_scale_destheight
  109.          mov decisiony, ax                  ;
  110.  
  111.          movsx eax, _cliptp                 ; if y is below the top
  112.          mov edx, eax                       ; clipping boundry, then we don't
  113.          sub dx, _scale_desty               ; need to clip the top, so we can
  114.          js s notopclip                     ; jump over the clipping stuff.
  115.  
  116.          mov _scale_desty, ax               ; this block performs clipping on the
  117.          sub clippedheight, dx              ; top of the _bitmap.  i have heavily
  118.          movsx ecx, sourceheight            ; optimized this block to use only 4
  119.          imul ecx, edx                      ; 32-bit registers, so i'm not even
  120.          mov eax, ecx                       ; gonna try to explain what it's doing.
  121.          cdq                                ; but i can tell you what results from
  122.          movsx ebx, _scale_destheight       ; this:  the decisiony var is updated
  123.          idiv ebx                           ; to start at the right clipped row.
  124.          movsx edx, sourcewidth             ; y is moved to the top clip
  125.          imul edx, eax                      ; boundry. clippedheight is lowered since
  126.          add esi, edx                       ; we won't be drawing all the requested
  127.          imul eax, ebx                      ; rows. esi is changed to point over
  128.          sub ecx, eax                       ; the _bitmap data that is clipped off.
  129.          sub ecx, ebx                       ;
  130.          add ecx, ecx                       ;
  131.          mov decisiony, cx                  ; <end of top clipping block >
  132.  
  133. notopclip:
  134.          mov ax, _scale_desty               ; if the _bitmap doesn't extend over the
  135.          add ax, clippedheight              ; bottom clipping boundry, then we
  136.          dec ax                             ; don't need to clip the bottom, so we
  137.          cmp ax, _clipbt                    ; can jump over the bottom clip code.
  138.          jle s nobottomclip                 ;
  139.  
  140.          mov ax, _clipbt                    ; clip off the bottom by reducing the
  141.          sub ax, _scale_desty               ; clippedheight so that the _bitmap won't
  142.          inc ax                             ; extend over the lower clipping
  143.          mov clippedheight, ax              ; boundry.
  144.  
  145. nobottomclip:
  146.          movsx eax, _cliplt                 ; if x is to the left of the
  147.          mov edx, eax                       ; top clipping boundry, then we don't
  148.          sub dx, _scale_destx               ; need to clip the left, so we can
  149.          js s noleftclip                    ; jump over the clipping stuff.
  150.  
  151.          mov _scale_destx, ax               ; this block performs clipping on the
  152.          sub clippedwidth, dx               ; left of the _bitmap.  i have heavily
  153.          movsx ecx, sourcewidth             ; optimized this block to use only 4
  154.          imul ecx, edx                      ; 32-bit registers, so i'm not even
  155.          mov eax, ecx                       ; gonna try to explain what it's doing.
  156.          cdq                                ; but i can tell you what results from
  157.          movsx ebx, _scale_destwidth        ; this:  the decisionx var is updated
  158.          idiv ebx                           ; to start at the right clipped column.
  159.          add esi, eax                       ; x is moved to the left clip
  160.          imul eax, ebx                      ; boundry. clippedwidth is reduced since
  161.          sub ecx, eax                       ; we won't be drawing all the requested
  162.          sub ecx, ebx                       ; cols. esi is changed to point over
  163.          add ecx, ecx                       ; the _bitmap data that is clipped off.
  164.          mov decisionx, cx                  ; <end of left clipping block >
  165.  
  166. noleftclip:
  167.          mov ax, _scale_destx               ; if the _bitmap doesn't extend over the
  168.          add ax, clippedwidth               ; right clipping boundry, then we
  169.          dec ax                             ; don't need to clip the right, so we
  170.          cmp ax, _cliprt                    ; can jump over the right clip code.
  171.          jle s noclipright                  ;
  172.  
  173.          mov ax, _cliprt                    ; clip off the right by reducing the
  174.          sub ax, _scale_destx               ; clippedwidth so that the _bitmap won't
  175.          inc ax                             ; extend over the right clipping
  176.          mov clippedwidth, ax               ; boundry.
  177.  
  178.          ;calculate starting video address
  179. noclipright:
  180.          xor edi,edi
  181.          mov di, _scale_desty               ; we are going to set edi to start point
  182.          imul edi, xactual/4
  183.          xor eax,eax
  184.          mov ax, _scale_destx               ; the offset edi is
  185.          mov cx, ax                         ; calculated by:
  186.          shr ax, 2                          ;     di = y*80+x/2
  187.          add eax, _current_page
  188.          add edi,eax                        ; edi is ready!
  189.  
  190.          mov dx, sc_index                   ; point the vga sequencer to the map
  191.          mov al, map_mask                   ; mask register, so that we only need
  192.          out dx, al                         ; to send out 1 byte per column.
  193.  
  194.          inc dx                             ; move to the sequencer's data register.
  195.          and cx, 3                          ; calculate the starting plane. this is
  196.          mov al, 11h                        ; just:
  197.          shl al, cl                         ; plane =  (11h << (x and 3))
  198.          out dx, al                         ; select the first plane.
  199.  
  200.          xor ecx,ecx
  201.          mov cx, sourcewidth                ; use cx for source width
  202.          mov xad, ecx
  203.          shl sourcewidth,1
  204.  
  205.          align 4                           ; since this point gets jumped to a lot,
  206.          ; make sure that it is dword aligned.
  207. rowloop:
  208.          push esi                           ; save the starting source index
  209.          push edi                           ; save the starting dest index
  210.          push ax                            ; save the current plane mask
  211.          push bp                            ; save the current base pointer
  212.  
  213.          mov cx, clippedheight              ; use al for row counter (0-239)
  214.          mov bx, decisiony                  ; use bx for decision variable
  215.          mov dx, sourceheight               ; use dx for source height * 2
  216.          add dx, dx
  217.          mov bp, _scale_destheight          ; use bp for dest height * 2
  218.          add bp, bp
  219.          mov ah, [esi]                      ; get the first source pixel
  220.  
  221.          align 4                            ; common jump point... align for speed.
  222. columnloop:
  223.          mov [edi], ah                      ; draw a pixel
  224.          dec cx                             ; decrement line counter
  225.          jz s donewithcol                   ; see if we're done with this column
  226.          add edi, xactual/4                 ; go on to the next screen row
  227.          add bx, dx                         ; increment the decision variable
  228.          js s columnloop                    ; draw this source pixel again
  229.  
  230. incsourcerow:
  231.          add esi, xad                       ; move to the next source pixel
  232.          sub bx, bp                         ; decrement the decision variable
  233.          jns s incsourcerow                 ; see if we need to skip another source pixel
  234.          mov ah, [esi]                      ; get the next source pixel
  235.          jmp s columnloop                   ; start drawing this pixel
  236.  
  237. donewithcol:
  238.          pop bp                             ; restore bp to access variables
  239.          pop ax                             ; restore al = plane mask
  240.          pop edi                            ; restore di to top row of screen
  241.          pop esi                            ; restore si to top row of source bits
  242.  
  243.          rol al, 1                          ; move to next plane
  244.          adc edi, 0                         ; go on to next screen column
  245.          mov dx, sc_data                    ; tell the vga what column we're in
  246.          out dx, al                         ; by updating the map mask register
  247.  
  248.          mov bx, decisionx                  ; use bx for the x decision variable
  249.          add bx, sourcewidth                ; increment the x decision variable
  250.          js s nextcol                       ; jump if we're still in the same source col.
  251.          mov dx, _scale_destwidth           ; dx = w * 2
  252.          add dx, dx
  253. incsourcecol:
  254.          inc esi                            ; move to next source column
  255.          sub bx, dx                         ; decrement x decision variable
  256.          jns s incsourcecol                 ; see if we skip another source column
  257. nextcol:
  258.          mov decisionx, bx                  ; free up bx for colloop
  259.          dec clippedwidth                   ; if we're not at last column
  260.          jnz rowloop                        ;    then do another column
  261. done:
  262.          ret                                ; we're done!
  263.  
  264. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  265. ;
  266. ; _tdraw_scale - Draw transparent scaled _bitmap in modex
  267. ; In:
  268. ;    ESI - offset of _bitmap to draw, first two words are x,y size
  269. ;     AX - x width to scale to
  270. ;     BX - y width to scale to
  271. ;     CX - x location, non-cartisian
  272. ;     DX - y location, non-cartisian
  273. ; _current_page - current offset of video memory for page of xmode, see xmode.asm
  274. ;
  275. ; Out:
  276. ;    null
  277. ;
  278. ; Notes:
  279. ;  transparent _bitmap.  any bytes that = 0 are skipped,- non-cartisian
  280. ;
  281. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  282.  
  283. _tdraw_scale:
  284.          mov _bitmap,esi
  285.          mov _scale_destwidth,ax
  286.          mov _scale_destheight,bx
  287.          mov _scale_destx,cx
  288.          mov _scale_desty,dx
  289.  
  290. _xscale2:
  291.          cmp _scale_destwidth, 2            ; if destination width is less than 2
  292.          jl s done                          ;     then don't draw it.
  293.  
  294.          cmp _scale_destheight, 2           ; if destination height is less than 2
  295.          jl s done                          ;     then don't draw it.
  296.  
  297.          mov ax, _scale_desty               ; if it is completely below the
  298.          cmp ax, _clipbt                    ; lower clip bondry,
  299.          jg s done                          ;     then don't draw it.
  300.  
  301.          add ax, _scale_destheight          ; if it is above clip boundries
  302.          dec ax                             ;     then don't draw it.
  303.          cmp ax, _cliptp
  304.          jl s done
  305.  
  306.          mov ax, _scale_destx               ; if it is to the right of the
  307.          mov cx, _cliprt                    ; right clip boundry
  308.          cmp ax, _cliprt                    ;     then don't draw it.
  309.          jg s done
  310.  
  311.          add ax, _scale_destwidth           ; if it is completely to the left
  312.          dec ax                             ; of the left clip boundry,
  313.          cmp ax, _cliplt                    ;     then don't draw it.
  314.          jl s done
  315.  
  316.          mov esi, _bitmap             ; make esi point to _bitmap data
  317.          lodsw                              ; get source x width
  318.          mov sourcewidth,ax
  319.          lodsw                              ; get source y height
  320.          mov sourceheight,ax
  321.  
  322.          mov ax, _scale_destwidth           ; clippedwidth is initially set to
  323.          mov clippedwidth, ax               ; the requested dest width.
  324.  
  325.          add ax,ax                          ; initialize the x decision var
  326.          neg ax                             ; to be -2*_scale_destwidth
  327.          mov decisionx, ax                  ;
  328.  
  329.          mov ax, _scale_destheight          ; clippedheight is initially set to
  330.          mov clippedheight, ax              ; the requested dest size.
  331.  
  332.          add ax,ax                          ; initialize the y decision var
  333.          neg ax                             ; to be -2*_scale_destheight
  334.          mov decisiony, ax                  ;
  335.  
  336.          movsx eax, _cliptp                 ; if y is below the top
  337.          mov edx, eax                       ; clipping boundry, then we don't
  338.          sub dx, _scale_desty               ; need to clip the top, so we can
  339.          js s notopclip2                    ; jump over the clipping stuff.
  340.  
  341.          mov _scale_desty, ax               ; this block performs clipping on the
  342.          sub clippedheight, dx              ; top of the _bitmap.  i have heavily
  343.          movsx ecx, sourceheight            ; optimized this block to use only 4
  344.          imul ecx, edx                      ; 32-bit registers, so i'm not even
  345.          mov eax, ecx                       ; gonna try to explain what it's doing.
  346.          cdq                                ; but i can tell you what results from
  347.          movsx ebx, _scale_destheight       ; this:  the decisiony var is updated
  348.          idiv ebx                           ; to start at the right clipped row.
  349.          movsx edx, sourcewidth             ; y is moved to the top clip
  350.          imul edx, eax                      ; boundry. clippedheight is lowered since
  351.          add esi, edx                       ; we won't be drawing all the requested
  352.          imul eax, ebx                      ; rows. esi is changed to point over
  353.          sub ecx, eax                       ; the _bitmap data that is clipped off.
  354.          sub ecx, ebx                       ;
  355.          add ecx, ecx                       ;
  356.          mov decisiony, cx                  ; <end of top clipping block >
  357.  
  358. notopclip2:
  359.          mov ax, _scale_desty               ; if the _bitmap doesn't extend over the
  360.          add ax, clippedheight              ; bottom clipping boundry, then we
  361.          dec ax                             ; don't need to clip the bottom, so we
  362.          cmp ax, _clipbt                    ; can jump over the bottom clip code.
  363.          jle s nobottomclip2
  364.  
  365.          mov ax, _clipbt                    ; clip off the bottom by reducing the
  366.          sub ax, _scale_desty               ; clippedheight so that the _bitmap won't
  367.          inc ax                             ; extend over the lower clipping
  368.          mov clippedheight, ax              ; boundry.
  369.  
  370. nobottomclip2:
  371.          movsx eax, _cliplt                 ; if x is to the left of the
  372.          mov edx, eax                       ; top clipping boundry, then we don't
  373.          sub dx, _scale_destx               ; need to clip the left, so we can
  374.          js s noleftclip2                   ; jump over the clipping stuff.
  375.  
  376.          mov _scale_destx, ax               ; this block performs clipping on the
  377.          sub clippedwidth, dx               ; left of the _bitmap.  i have heavily
  378.          movsx ecx, sourcewidth             ; optimized this block to use only 4
  379.          imul ecx, edx                      ; 32-bit registers, so i'm not even
  380.          mov eax, ecx                       ; gonna try to explain what it's doing.
  381.          cdq                                ; but i can tell you what results from
  382.          movsx ebx, _scale_destwidth        ; this:  the decisionx var is updated
  383.          idiv ebx                           ; to start at the right clipped column.
  384.          add esi, eax                       ; x is moved to the left clip
  385.          imul eax, ebx                      ; boundry. clippedwidth is reduced since
  386.          sub ecx, eax                       ; we won't be drawing all the requested
  387.          sub ecx, ebx                       ; cols. esi is changed to point over
  388.          add ecx, ecx                       ; the _bitmap data that is clipped off.
  389.          mov decisionx, cx                  ; <end of left clipping block >
  390.  
  391. noleftclip2:
  392.          mov ax, _scale_destx               ; if the _bitmap doesn't extend over the
  393.          add ax, clippedwidth               ; right clipping boundry, then we
  394.          dec ax                             ; don't need to clip the right, so we
  395.          cmp ax, _cliprt                    ; can jump over the right clip code.
  396.          jle s noclipright2
  397.  
  398.          mov ax, _cliprt                    ; clip off the right by reducing the
  399.          sub ax, _scale_destx               ; clippedwidth so that the _bitmap won't
  400.          inc ax                             ; extend over the right clipping
  401.          mov clippedwidth, ax               ; boundry.
  402.  
  403.          ;calculate starting video address
  404. noclipright2:
  405.          movsx edi, _scale_desty            ; we are going to set edi to start point
  406.          imul edi, xactual/4
  407.          movsx eax, _scale_destx            ; the offset edi is
  408.          mov cx, ax                         ; calculated by:
  409.          shr eax, 2                         ; edi = y*80+x/2
  410.          add eax, _current_page
  411.          add edi,eax                        ; edi is ready!
  412.  
  413.          mov dx, sc_index                   ; point the vga sequencer to the map
  414.          mov al, map_mask                   ; mask register, so that we only need
  415.          out dx, al                         ; to send out 1 byte per column.
  416.  
  417.          inc dx                             ; move to the sequencer's data register.
  418.          and cx, 3                          ; calculate the starting plane. this is
  419.          mov al, 11h                        ; just:
  420.          shl al, cl                         ; plane =  (11h << (x and 3))
  421.          out dx, al                         ; select the first plane.
  422.  
  423.          xor ecx,ecx
  424.          mov cx, sourcewidth                ; use cx for source width
  425.          mov xad, ecx
  426.          shl sourcewidth,1
  427.  
  428.          align 4                           ; since this point gets jumped to a lot,
  429.          ; make sure that it is dword aligned.
  430. rowloop2:
  431.          push esi                           ; save the starting source index
  432.          push edi                           ; save the starting dest index
  433.          push ax                            ; save the current plane mask
  434.          push bp                            ; save the current base pointer
  435.  
  436.          mov cx, clippedheight              ; use al for row counter (0-239)
  437.          mov bx, decisiony                  ; use bx for decision variable
  438.          mov dx, sourceheight               ; use dx for source height * 2
  439.          add dx, dx
  440.          mov bp, _scale_destheight          ; use bp for dest height * 2
  441.          add bp, bp
  442.          mov ah, [esi]                      ; get the first source pixel
  443.          or ah,ah
  444.          jz s null_loop                     ; if zero, perform null loop
  445.  
  446.          align 4                            ; common jump point... align for speed.
  447. columnloop2:
  448.          mov [edi], ah                      ; draw a pixel
  449.          dec cx                             ; decrement line counter
  450.          jz s donewithcol2                  ; see if we're done with this column
  451.          add edi, xactual/4                 ; go on to the next screen row
  452.          add bx, dx                         ; increment the decision variable
  453.          js s columnloop2                   ; draw this source pixel again
  454.  
  455. incsourcerow2:
  456.          add esi, xad                       ; move to the next source pixel
  457.          sub bx, bp                         ; decrement the decision variable
  458.          jns s incsourcerow2                ; see if we need to skip another source pixel
  459.          mov ah, [esi]                      ; get the next source pixel
  460.          cmp ah,0
  461.          jz s null_loop
  462.          jmp s columnloop2                  ; start drawing this pixel
  463.  
  464. donewithcol2:
  465.          pop bp                             ; restore bp to access variables
  466.          pop ax                             ; restore al = plane mask
  467.          pop edi                            ; restore di to top row of screen
  468.          pop esi                            ; restore si to top row of source bits
  469.  
  470.          rol al, 1                          ; move to next plane
  471.          adc edi, 0                         ; go on to next screen column
  472.          mov dx, sc_data                    ; tell the vga what column we're in
  473.          out dx, al                         ; by updating the map mask register
  474.  
  475.          mov bx, decisionx                  ; use bx for the x decision variable
  476.          add bx, sourcewidth                ; increment the x decision variable
  477.          js s nextcol2                      ; jump if we're still in the same source col.
  478.          mov dx, _scale_destwidth           ; dx = w * 2
  479.          add dx, dx
  480. incsourcecol2:
  481.          inc esi                            ; move to next source column
  482.          sub bx, dx                         ; decrement x decision variable
  483.          jns s incsourcecol2                ; see if we skip another source column
  484. nextcol2:
  485.          mov decisionx, bx                  ; free up bx for colloop
  486.          dec clippedwidth                   ; if we're not at last column
  487.          jnz rowloop2                       ;    then do another column
  488. done2:
  489.          ret                                ; we're done!
  490.  
  491.          align 4                           ; common jump point... align for speed.
  492. null_loop:
  493.          dec cx                             ; decrement line counter
  494.          jz s donewithcol2                  ; see if we're done with this column
  495.          add edi, xactual/4                 ; go on to the next screen row
  496.          add bx, dx                         ; increment the decision variable
  497.          js s null_loop                     ; perform more increments
  498.          jmp s incsourcerow2
  499.  
  500. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  501. ;
  502. ; _repeat_bitmap - Draw repeated bit map.
  503. ; In:
  504. ;    REGS = none
  505. ; Stack frame:
  506. ;    DWORD: offset to _bitmap
  507. ;     WORD: left   x of window - non-cartisian...
  508. ;     WORD: top    y of window
  509. ;     WORD: right  x of window
  510. ;     WORD: bottom y of window
  511. ; MEMORY:
  512. ; _current_page - current offset of video memory for page of xmode, see xmode.asm
  513. ;
  514. ; Out:
  515. ;    null
  516. ;
  517. ; Notes:
  518. ;
  519. ; Good for _backgrounds in menus and title  screens.
  520. ; routine is NOT intended for animation because it is slow. uses scale routine
  521. ; because scale routine clips bitmaps.  Sloppy routine just draws all over the
  522. ; place and lets the scale clip borders handle the rest.
  523. ;
  524. ; remember: first two words of bitmap define width and height
  525. ;
  526. ; From C (Ug...)
  527. ; _repeat_bitmap (off bitmap, _x1%, _y1%, _x2%, _y2%)
  528. ;
  529. ; From assembley (oh, yes)
  530. ;
  531. ; push offset bitmaptorepeat
  532. ; push _x1
  533. ; push _y1
  534. ; push _x2
  535. ; push _y2
  536. ; call _repeat_bitmap
  537. ;
  538. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  539.  
  540. rb_stack struc
  541.          rb_wide dw ?                       ; height and width of _bitmap
  542.          rb_height dw ?
  543.          rb_curx dw ?                       ; current _bitmap location
  544.          rb_cury dw ?
  545.          rb_old_y2 dw ?                     ; old cliping borders save
  546.          rb_old_x2 dw ?
  547.          rb_old_y1 dw ?
  548.          rb_old_x1 dw ?
  549.          dd ?x3                             ; edi, esi, ebp
  550.          dd ?                               ; caller
  551.          rb_y2 dw ?                         ; _y2
  552.          rb_x2 dw ?                         ; _x2
  553.          rb_y1 dw ?                         ; _y1
  554.          rb_x1 dw ?                         ; _x1
  555.          rb_bitmap dd ?               ; offset to _bitmap
  556. rb_stack ends
  557.  
  558. _repeat_bitmap:
  559.          push ebp esi edi                   ; preserve important registers
  560.          sub esp, 16                        ; allocate workspace
  561.          mov ebp, esp                       ; set up stack frame
  562.  
  563.          mov ax,_cliplt                     ; save old borders just in case
  564.          mov [ebp].rb_old_x1,ax
  565.          mov ax,_cliprt
  566.          mov [ebp].rb_old_x2,ax
  567.          mov ax,_cliptp
  568.          mov [ebp].rb_old_y1,ax
  569.          mov ax,_clipbt
  570.          mov [ebp].rb_old_y2,ax
  571.  
  572.          mov _x1,4
  573.  
  574.          mov ax,[ebp].rb_x1                 ; set new borders for clipping
  575.          mov _cliplt,ax
  576.          mov ax,[ebp].rb_x2
  577.          mov _cliprt,ax
  578.          mov ax,[ebp].rb_y1
  579.          mov _cliptp,ax
  580.          mov ax,[ebp].rb_y2
  581.          mov _clipbt,ax
  582.  
  583.          mov [ebp].rb_curx,0                ; we could start at _x1,_y1 but this
  584.          mov [ebp].rb_cury,0                ; will make offset _backgrounds
  585.  
  586.          mov esi,[ebp].rb_bitmap
  587.          mov _bitmap,esi
  588.          lodsw                              ; set destination width same as original
  589.          mov [ebp].rb_wide,ax
  590.          lodsw
  591.          mov [ebp].rb_height,ax
  592. nextline:
  593.          mov ax,[ebp].rb_wide
  594.          mov _scale_destwidth,ax
  595.          mov ax,[ebp].rb_height
  596.          mov _scale_destheight,ax
  597.  
  598.          mov ax,[ebp].rb_curx
  599.          mov _scale_destx,ax
  600.          mov ax,[ebp].rb_cury
  601.          mov _scale_desty,ax
  602.  
  603.          push ebp
  604.          call _xscale2                      ; draw a transparent _bitmap
  605.          pop ebp
  606.  
  607.          mov ax,[ebp].rb_curx
  608.          add ax,[ebp].rb_wide
  609.          mov [ebp].rb_curx,ax
  610.          cmp ax,[ebp].rb_x2
  611.          jle s nextline
  612.  
  613.          mov [ebp].rb_curx,0
  614.  
  615.          mov ax,[ebp].rb_cury
  616.          add ax,[ebp].rb_height
  617.          mov [ebp].rb_cury,ax
  618.          cmp ax,[ebp].rb_y2
  619.          jle s nextline
  620.  
  621.          mov ax,[ebp].rb_old_x1
  622.          mov _cliplt,ax
  623.          mov ax,[ebp].rb_old_x2
  624.          mov _cliprt,ax
  625.          mov ax,[ebp].rb_old_y1
  626.          mov _cliptp,ax
  627.          mov ax,[ebp].rb_old_y2
  628.          mov _clipbt,ax
  629.  
  630.          add esp, 16
  631.          pop edi esi ebp
  632.          ret 12
  633.  
  634. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  635. ;
  636. ; _tdraw_scale4 - Draw transparent scaled bitmap using 1/4 xmode method:
  637. ;                draws every 4th pixel alike.
  638. ; In:
  639. ;    ESI - offset of _bitmap to draw, first two words are x,y size
  640. ;     AX - x width to scale to
  641. ;     BX - y width to scale to
  642. ;     CX - x location, non-cartisian
  643. ;     DX - y location, non-cartisian
  644. ; _current_page - current offset of video memory for page of xmode, see xmode.asm
  645. ;
  646. ; Out:
  647. ;    null
  648. ;
  649. ; Notes:
  650. ;  great  for  explosions/smoke  where  the  _bitmap  does  not have to be  very
  651. ;  accuratly drawn - much faster
  652. ;
  653. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  654.  
  655. done4:   ret
  656.  
  657. _tdraw_scale4:
  658.          mov _bitmap,esi
  659.          mov _scale_destwidth,ax
  660.          mov _scale_destheight,bx
  661.          mov _scale_destx,cx
  662.          mov _scale_desty,dx
  663.  
  664. _xscale4:
  665.          cmp _scale_destwidth, 2            ; if destination width is less than 2
  666.          jl s done4                         ;     then don't draw it.
  667.  
  668.          cmp _scale_destheight, 2           ; if destination height is less than 2
  669.          jl s done4                         ;     then don't draw it.
  670.  
  671.          mov ax, _scale_desty               ; if it is completely below the
  672.          cmp ax, _clipbt                    ; lower clip bondry,
  673.          jg s done4                         ;     then don't draw it.
  674.  
  675.          add ax, _scale_destheight          ; if it is above clip boundries
  676.          dec ax                             ;     then don't draw it.
  677.          cmp ax, _cliptp
  678.          jl s done4
  679.  
  680.          mov ax, _scale_destx               ; if it is to the right of the
  681.          mov cx, _cliprt                    ; right clip boundry
  682.          cmp ax, _cliprt                    ;     then don't draw it.
  683.          jg s done4
  684.  
  685.          add ax, _scale_destwidth           ; if it is completely to the left
  686.          dec ax                             ; of the left clip boundry,
  687.          cmp ax, _cliplt                    ;     then don't draw it.
  688.          jl s done4
  689.  
  690.          mov esi, _bitmap             ; make esi point to _bitmap data
  691.          lodsw                              ; get source x width
  692.          mov sourcewidth,ax
  693.          lodsw                              ; get source y height
  694.          mov sourceheight,ax
  695.  
  696.          mov ax, _scale_destwidth           ; clippedwidth is initially set to
  697.          mov clippedwidth, ax               ; the requested dest width.
  698.  
  699.          add ax,ax                          ; initialize the x decision var
  700.          neg ax                             ; to be -2*_scale_destwidth
  701.          mov decisionx, ax                  ;
  702.  
  703.          mov ax, _scale_destheight          ; clippedheight is initially set to
  704.          mov clippedheight, ax              ; the requested dest size.
  705.  
  706.          add ax,ax                          ; initialize the y decision var
  707.          neg ax                             ; to be -2*_scale_destheight
  708.          mov decisiony, ax                  ;
  709.  
  710.          movsx eax, _cliptp                 ; if y is below the top
  711.          mov edx, eax                       ; clipping boundry, then we don't
  712.          sub dx, _scale_desty               ; need to clip the top, so we can
  713.          js s notopclip4                    ; jump over the clipping stuff.
  714.  
  715.          mov _scale_desty, ax               ; this block performs clipping on the
  716.          sub clippedheight, dx              ; top of the _bitmap.  i have heavily
  717.          movsx ecx, sourceheight            ; optimized this block to use only 4
  718.          imul ecx, edx                      ; 32-bit registers, so i'm not even
  719.          mov eax, ecx                       ; gonna try to explain what it's doing.
  720.          cdq                                ; but i can tell you what results from
  721.          movsx ebx, _scale_destheight       ; this:  the decisiony var is updated
  722.          idiv ebx                           ; to start at the right clipped row.
  723.          movsx edx, sourcewidth             ; y is moved to the top clip
  724.          imul edx, eax                      ; boundry. clippedheight is lowered since
  725.          add esi, edx                       ; we won't be drawing all the requested
  726.          imul eax, ebx                      ; rows. esi is changed to point over
  727.          sub ecx, eax                       ; the _bitmap data that is clipped off.
  728.          sub ecx, ebx                       ;
  729.          add ecx, ecx                       ;
  730.          mov decisiony, cx                  ; <end of top clipping block >
  731.  
  732. notopclip4:
  733.          mov ax, _scale_desty               ; if the _bitmap doesn't extend over the
  734.          add ax, clippedheight              ; bottom clipping boundry, then we
  735.          dec ax                             ; don't need to clip the bottom, so we
  736.          cmp ax, _clipbt                    ; can jump over the bottom clip code.
  737.          jle s nobottomclip4
  738.  
  739.          mov ax, _clipbt                    ; clip off the bottom by reducing the
  740.          sub ax, _scale_desty               ; clippedheight so that the _bitmap won't
  741.          inc ax                             ; extend over the lower clipping
  742.          mov clippedheight, ax              ; boundry.
  743.  
  744. nobottomclip4:
  745.          movsx eax, _cliplt                 ; if x is to the left of the
  746.          mov edx, eax                       ; top clipping boundry, then we don't
  747.          sub dx, _scale_destx               ; need to clip the left, so we can
  748.          js s noleftclip4                   ; jump over the clipping stuff.
  749.  
  750.          mov _scale_destx, ax               ; this block performs clipping on the
  751.          sub clippedwidth, dx               ; left of the _bitmap.  i have heavily
  752.          movsx ecx, sourcewidth             ; optimized this block to use only 4
  753.          imul ecx, edx                      ; 32-bit registers, so i'm not even
  754.          mov eax, ecx                       ; gonna try to explain what it's doing.
  755.          cdq                                ; but i can tell you what results from
  756.          movsx ebx, _scale_destwidth        ; this:  the decisionx var is updated
  757.          idiv ebx                           ; to start at the right clipped column.
  758.          add esi, eax                       ; x is moved to the left clip
  759.          imul eax, ebx                      ; boundry. clippedwidth is reduced since
  760.          sub ecx, eax                       ; we won't be drawing all the requested
  761.          sub ecx, ebx                       ; cols. esi is changed to point over
  762.          add ecx, ecx                       ; the _bitmap data that is clipped off.
  763.          mov decisionx, cx                  ; <end of left clipping block >
  764.  
  765. noleftclip4:
  766.          mov ax, _scale_destx               ; if the _bitmap doesn't extend over the
  767.          add ax, clippedwidth               ; right clipping boundry, then we
  768.          dec ax                             ; don't need to clip the right, so we
  769.          cmp ax, _cliprt                    ; can jump over the right clip code.
  770.          jle s noclipright4
  771.  
  772.          mov ax, _cliprt                    ; clip off the right by reducing the
  773.          sub ax, _scale_destx               ; clippedwidth so that the _bitmap won't
  774.          inc ax                             ; extend over the right clipping
  775.          mov clippedwidth, ax               ; boundry.
  776.  
  777.          ;calculate starting video address
  778. noclipright4:
  779.          movsx edi, _scale_desty            ; we are going to set edi to start point
  780.          imul edi, xactual/4
  781.          movsx eax, _scale_destx            ; the offset edi is
  782.          mov cx, ax                         ; calculated by:
  783.          shr eax, 2                         ; edi = y*80+x/2
  784.          add eax, _current_page
  785.          add edi,eax                        ; edi is ready!
  786.  
  787.          mov dx, sc_index                   ; point the vga sequencer to the map
  788.          mov al, map_mask                   ; mask register, so that we only need
  789.          out dx, al                         ; to send out 1 byte per column.
  790.  
  791.          inc dx                             ; move to the sequencer's data register.
  792.          mov al, all_planes
  793.          out dx, al                         ; select the first plane.
  794.  
  795.          xor ecx,ecx
  796.          mov cx, sourcewidth                ; use cx for source width
  797.          mov xad, ecx
  798.  
  799.          shl sourcewidth,1+2                ; 4 times as fast
  800.          shr clippedwidth,2                 ; 1/4 of the plots
  801.  
  802.          cmp clippedwidth,0                 ; check if <4 wide
  803.          jne s rowloop4
  804.          inc clippedwidth
  805.  
  806.          align 4                           ; since this point gets jumped to a lot,
  807.          ; make sure that it is dword aligned.
  808. rowloop4:
  809.          push esi                           ; save the starting source index
  810.          push edi                           ; save the starting dest index
  811.          push bp                            ; save the current base pointer
  812.  
  813.          mov cx, clippedheight              ; use al for row counter (0-239)
  814.          mov bx, decisiony                  ; use bx for decision variable
  815.          mov dx, sourceheight               ; use dx for source height * 2
  816.          add dx, dx
  817.          mov bp, _scale_destheight          ; use bp for dest height * 2
  818.          add bp, bp
  819.          mov ah, [esi]                      ; get the first source pixel
  820.          or ah,ah
  821.          jz s null_loop4                    ; if zero, perform null loop
  822.  
  823.          align 4                            ; common jump point... align for speed.
  824. columnloop4:
  825.          mov [edi], ah                      ; draw a pixel
  826.          dec cx                             ; decrement line counter
  827.          jz s donewithcol4                  ; see if we're done with this column
  828.          add edi, xactual/4                 ; go on to the next screen row
  829.          add bx, dx                         ; increment the decision variable
  830.          js s columnloop4                   ; draw this source pixel again
  831.  
  832. incsourcerow4:
  833.          add esi, xad                       ; move to the next source pixel
  834.          sub bx, bp                         ; decrement the decision variable
  835.          jns s incsourcerow4                ; see if we need to skip another source pixel
  836.          mov ah, [esi]                      ; get the next source pixel
  837.          or ah,ah
  838.          jz s null_loop4
  839.          jmp s columnloop4                  ; start drawing this pixel
  840.  
  841. donewithcol4:
  842.          pop bp                             ; restore bp to access variables
  843.          pop edi                            ; restore di to top row of screen
  844.          pop esi                            ; restore si to top row of source bits
  845.  
  846.          add edi, 1                         ; go on to next screen column
  847.  
  848.          mov bx, decisionx                  ; use bx for the x decision variable
  849.          add bx, sourcewidth                ; increment the x decision variable
  850.          mov dx, _scale_destwidth           ; dx = w * 2
  851.          add dx, dx
  852. incsourcecol4:
  853.          inc esi                            ; move to next source column
  854.          sub bx, dx                         ; decrement x decision variable
  855.          jns s incsourcecol4                ; see if we skip another source column
  856. nextcol4:
  857.          mov decisionx, bx                  ; free up bx for colloop
  858.          dec clippedwidth                   ; if we're not at last column
  859.          jnz rowloop4                       ;    then do another column
  860.  
  861.          ret                                ; we're done!
  862.  
  863.          align 4                           ; common jump point... align for speed.
  864. null_loop4:
  865.          dec cx                             ; decrement line counter
  866.          jz s donewithcol4                  ; see if we're done with this column
  867.          add edi, xactual/4                 ; go on to the next screen row
  868.          add bx, dx                         ; increment the decision variable
  869.          js s null_loop4                    ; perform more increments
  870.          jmp s incsourcerow4
  871.  
  872.